package com.dl.base.utils

import android.os.Handler
import android.os.Looper
import android.os.Message
import java.util.concurrent.TimeUnit

typealias block = () -> Unit

enum class IntervalModel {
    FIRST, DOUBLE, LAST
}

fun intervalHandler2(
    interval: Long = 1000L,
    timeUnit: TimeUnit = TimeUnit.MILLISECONDS,
    model: IntervalModel = IntervalModel.FIRST
): (success: block, failure: block) -> Unit {
    var intervalHandlerTime = 0L
    val intervalTime = timeUnit.toMillis(interval)

    return { success, failure ->
        interval(intervalTime, intervalHandlerTime, model, success, failure)?.let {
            intervalHandlerTime = it
        }
    }
}

fun intervalHandler(
    interval: Long = 1000L,
    timeUnit: TimeUnit = TimeUnit.MILLISECONDS,
    model: IntervalModel = IntervalModel.FIRST
): (success: block) -> Unit {
    var intervalHandlerTime = 0L
    val intervalTime = timeUnit.toMillis(interval)
    return { success ->
        interval(intervalTime, intervalHandlerTime, model, success)?.let {
            intervalHandlerTime = it
        }
    }
}

private inline fun interval(
    interval: Long,
    intervalHandlerTime: Long,
    model: IntervalModel,
    success: block,
    failure: block = {}
): Long? {
    val time = System.currentTimeMillis()
    return when (model) {
        IntervalModel.FIRST -> intervalFirst(time, interval, intervalHandlerTime, success, failure)
        IntervalModel.DOUBLE -> intervalDouble(
            time,
            interval,
            intervalHandlerTime,
            success,
            failure
        )
        IntervalModel.LAST -> intervalLast(time, interval, intervalHandlerTime, success, failure)
    }
}

private inline fun intervalFirst(
    time: Long, interval: Long,
    intervalHandlerTime: Long,
    success: block,
    failure: block = {}
): Long? {
    return if (time - intervalHandlerTime > interval) {
        success()
        time
    } else {
        failure()
        null
    }
}

private inline fun intervalDouble(
    time: Long, interval: Long,
    intervalHandlerTime: Long,
    success: block,
    failure: block = {}
): Long? {
    return if (time - intervalHandlerTime > interval) {
        failure()
        time
    } else {
        success()
        null
    }
}

private inline fun intervalLast(
    time: Long, interval: Long,
    intervalHandlerTime: Long,
    success: block,
    failure: block = {}
): Long? {
    return if (intervalHandlerTime == 0L) {
        failure()
        time
    } else {
        if (time - intervalHandlerTime < interval) {
            failure()
            null
        } else {
            success()
            time
        }
    }
}

class FilterHandler(private val interval: Long, private val block: () -> Unit) :
    Handler(Looper.getMainLooper()) {

    override fun handleMessage(msg: Message) {
        if (msg.what == 1) {
            block()
        }
    }

    fun sendEvent() {
        if (hasMessages(1)) {
            removeMessages(1)
        }
        sendEmptyMessageDelayed(1, interval)
    }
}
